package cc.rengu.igas.opms.core.service.trans.common;

import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.core.service.base.ManageService;
import cc.rengu.igas.opms.facade.request.ModifyUserPhoneRequest;
import cc.rengu.igas.opms.facade.response.ModifyUserPhoneResponse;
import cc.rengu.igas.share.common.constant.UserSessionConstant;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.NonFinanceTxnMapper;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.NonFinanceTxnMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.NonFinanceTxn;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.common.enums.SmsTypeEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.SmsService;
import cc.rengu.oltp.service.realize.impl.SmsServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 修改用户手机号
 * Created by liujinan on 2020/4/17.
 * modify by wangcheng 2021-09-13
 */
public class ModifyUserPhoneService extends ManageService {
    @Override
    protected Object bizBeforeCust() throws Exception {
        ModifyUserPhoneRequest modifyUserPhoneRequest = new ModifyUserPhoneRequest();
        ConvertUtil.convertOutput(modifyUserPhoneRequest);
        return modifyUserPhoneRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        BizResponse<ModifyUserPhoneResponse> bizResponse = new BizResponse<>();
        ModifyUserPhoneResponse modifyUserPhoneResponse = new ModifyUserPhoneResponse();
        bizResponse.setRspSysId(AppParamConstant.IGAS);
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        ModifyUserPhoneRequest modifyUserPhoneRequest = (ModifyUserPhoneRequest) request;
        String instId = modifyUserPhoneRequest.getHeader().getInstId();
        String userId = modifyUserPhoneRequest.getUserId();
        String txnMode = modifyUserPhoneRequest.getTxnMode();
        String newPhoneNo = modifyUserPhoneRequest.getPhoneNo();

        //校验会话
        UserService userService = new UserServiceImpl();
        UserInfo userInfo = userService.getUserInfo(instId, userId, modifyUserPhoneRequest.getHeader().getSession());
        if (null == userInfo) {
            rglog.error("获取用户信息失败!");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        //获取用户的签约主体
        String signInst = userService.getUserSignInst();

        //交易类别 00-身份验证
        if ("00".equals(txnMode)) {
            String authMode = modifyUserPhoneRequest.getCustAuthInfo().getAuthMode();
            rglog.debug("修改用户手机号-身份验证，验证方式authMode:<{}>", authMode);
            switch (authMode) {
                //手机号+支付密码
                case "00": {
                    String phoneNo = modifyUserPhoneRequest.getCustAuthInfo().getPhoneNo();
                    //校验手机号
                    if (!userInfo.getMobileNo().equals(phoneNo)) {
                        rglog.error("用户手机号与上送手机号不匹配！");
                        throw new BizException(RespCodeEnum.USER_INFO_MISMATCH.getRespCode(), RespCodeEnum.USER_INFO_MISMATCH.getRespDesc());
                    }
                    //查询短信验证码表，校验短信验证码
                    String smsCode = modifyUserPhoneRequest.getCustAuthInfo().getSmsCode();
                    String smsVerifySeqNum = modifyUserPhoneRequest.getCustAuthInfo().getSmsVerifySeqNum();
                    SmsService smsService = new SmsServiceImpl();
                    smsService.verifySmsCode(instId, SmsTypeEnum.IDENTITY_AUTH.getSmsType(), smsCode, smsVerifySeqNum);
                    //校验支付密码
                    boolean checkResult = userService.checkUserPayPassword(instId, modifyUserPhoneRequest.getUserId(), null, modifyUserPhoneRequest.getCustAuthInfo().getPassword());
                    if (!checkResult) {
                        rglog.error("用户密码错误!");
                        throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
                    }
                    break;
                }
                //银行卡+支付密码
                case "01": {
                    //判断输入的银行卡和选择绑定的银行卡是否一致
                    if (!modifyUserPhoneRequest.getCustAuthInfo().getBindPayAcctNo().equals(modifyUserPhoneRequest.getCustAuthInfo().getPayAcctNo())) {
                        rglog.info("输入的银行卡号:<{}>与绑定的银行卡号:<{}>不一致",
                                modifyUserPhoneRequest.getCustAuthInfo().getPayAcctNo(), modifyUserPhoneRequest.getCustAuthInfo().getBindPayAcctNo());
                        throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
                    }
                    //校验支付密码
                    boolean checkResult = userService.checkUserPayPassword(instId, modifyUserPhoneRequest.getUserId(), null, modifyUserPhoneRequest.getCustAuthInfo().getPassword());
                    if (!checkResult) {
                        rglog.error("用户密码错误!");
                        throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
                    }
                    //银行卡号字段（payAcctNo）查询签约信息表，验证证件号码字段
                    String payAcctNo = modifyUserPhoneRequest.getCustAuthInfo().getPayAcctNo();
                    String certNo = modifyUserPhoneRequest.getCustAuthInfo().getCertNo();
                    SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
                    List<SignAcctInfo> signAcctInfos = signAcctInfoMapper.selectSignAcctInfoBySignAcctNo(instId, payAcctNo);
                    if (null == signAcctInfos || signAcctInfos.isEmpty()) {
                        rglog.info("用户签约信息不存在");
                        throw new BizException(RespCodeEnum.GET_SIGN_INFO_ERROR.getRespCode(), RespCodeEnum.GET_SIGN_INFO_ERROR.getRespDesc());
                    } else {
                        signAcctInfos = signAcctInfos.stream().filter(item -> item.getSignInst().equals(signInst) &&
                                item.getSignStatus().equals(AppParamConstant.YES)).collect(Collectors.toList());
                    }
                    //筛选当前证件做的签约交易
                    List<SignAcctInfo> certTypeSignAcctInfos = signAcctInfos.stream().filter(item -> modifyUserPhoneRequest.getCustAuthInfo().getCertType().equals(item.getCertType())).collect(Collectors.toList());
                    if (certTypeSignAcctInfos.isEmpty()) {
                        rglog.info("用户未使用当前证件做签约交易,requestCertType:<{}>", modifyUserPhoneRequest.getCustAuthInfo().getCertType());
                        throw new BizException(RespCodeEnum.USER_INFO_MISMATCH.getRespCode(), RespCodeEnum.USER_INFO_MISMATCH.getRespDesc());
                    }
                    //校验上送的证件号是否一致
                    SignAcctInfo signAcctInfo = certTypeSignAcctInfos.get(0);
                    if (!signAcctInfo.getCertNo().equals(certNo)) {
                        rglog.info("用户证件信息不匹配,exitCertType:<{}>,exitCertNo:<{}>,reqCertType:<{}>,reqCertNo:<{}>",
                                signAcctInfo.getCertType(), signAcctInfo.getCertNo(), modifyUserPhoneRequest.getCustAuthInfo().getCertType(), modifyUserPhoneRequest.getCustAuthInfo().getCertNo());
                        throw new BizException(RespCodeEnum.USER_INFO_MISMATCH.getRespCode(), RespCodeEnum.USER_INFO_MISMATCH.getRespDesc());
                    }
                    break;
                }
                //银行卡+手机号
                case "02": {
                    //判断输入的银行卡和选择绑定的银行卡是否一致
                    if (!modifyUserPhoneRequest.getCustAuthInfo().getBindPayAcctNo().equals(modifyUserPhoneRequest.getCustAuthInfo().getPayAcctNo())) {
                        rglog.info("输入的银行卡号:<{}>与绑定的银行卡号:<{}>不一致",
                                modifyUserPhoneRequest.getCustAuthInfo().getPayAcctNo(), modifyUserPhoneRequest.getCustAuthInfo().getBindPayAcctNo());
                        throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
                    }
                    //校验手机号
                    if (!userInfo.getMobileNo().equals(modifyUserPhoneRequest.getCustAuthInfo().getPhoneNo())) {
                        rglog.error("手机号信息不匹配，userBindPhoneNo:<{}>,requestPhoneNo:<{}>", userInfo.getMobileNo(), modifyUserPhoneRequest.getCustAuthInfo().getPhoneNo());
                        throw new BizException(RespCodeEnum.USER_INFO_MISMATCH.getRespCode(), RespCodeEnum.USER_INFO_MISMATCH.getRespDesc());
                    }
                    //查询短信验证码表（T_P_SMS_INFO），校验短信验证码
                    String smsCode = modifyUserPhoneRequest.getCustAuthInfo().getSmsCode();
                    String smsVerifySeqNum = modifyUserPhoneRequest.getCustAuthInfo().getSmsVerifySeqNum();
                    SmsService smsService = new SmsServiceImpl();
                    smsService.verifySmsCode(instId, SmsTypeEnum.IDENTITY_AUTH.getSmsType(), smsCode, smsVerifySeqNum);
                    // 银行卡号字段（payAcctNo）查询签约信息表，验证证件号码字段
                    String certNo = modifyUserPhoneRequest.getCustAuthInfo().getCertNo();
                    SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
                    List<SignAcctInfo> signAcctInfos = signAcctInfoMapper.selectSignAcctInfoBySignAcctNo(instId, modifyUserPhoneRequest.getCustAuthInfo().getPayAcctNo());
                    if (null == signAcctInfos || signAcctInfos.isEmpty()) {
                        rglog.error("用户有效的签约关不存在，instId:<{}>,signInst:<{}>,payAcctNo:<{}>", instId, signInst, modifyUserPhoneRequest.getCustAuthInfo().getPayAcctNo());
                        throw new BizException(RespCodeEnum.GET_SIGN_INFO_ERROR.getRespCode(), RespCodeEnum.GET_SIGN_INFO_ERROR.getRespDesc());
                    } else {
                        signAcctInfos = signAcctInfos.stream().filter(item -> item.getSignInst().equals(signInst) &&
                                item.getSignStatus().equals(AppParamConstant.YES)).collect(Collectors.toList());
                    }
                    //筛选当前证件做的签约交易
                    List<SignAcctInfo> certTypeSignAcctInfos = signAcctInfos.stream().filter(item -> modifyUserPhoneRequest.getCustAuthInfo().getCertType().equals(item.getCertType())).collect(Collectors.toList());
                    if (certTypeSignAcctInfos.isEmpty()) {
                        rglog.info("用户未使用当前证件做签约交易,requestCertType:<{}>", modifyUserPhoneRequest.getCustAuthInfo().getCertType());
                        throw new BizException(RespCodeEnum.USER_INFO_MISMATCH.getRespCode(), RespCodeEnum.USER_INFO_MISMATCH.getRespDesc());
                    }
                    //校验上送的证件号是否一致
                    SignAcctInfo signAcctInfo = certTypeSignAcctInfos.get(0);
                    if (!signAcctInfo.getCertNo().equals(certNo)) {
                        rglog.info("用户证件信息不匹配,exitCertType:<{}>,exitCertNo:<{}>,reqCertType:<{}>,reqCertNo:<{}>",
                                signAcctInfo.getCertType(), signAcctInfo.getCertNo(), modifyUserPhoneRequest.getCustAuthInfo().getCertType(), modifyUserPhoneRequest.getCustAuthInfo().getCertNo());
                        throw new BizException(RespCodeEnum.USER_INFO_MISMATCH.getRespCode(), RespCodeEnum.USER_INFO_MISMATCH.getRespDesc());
                    }
                    break;
                }
                default: {
                    rglog.info("认证方式错误,authMode:<{}>", authMode);
                    throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
                }
            }
            /* 设置修改用户手机号的交易流水号到用户会话缓存中,在获取短信验证码时提前校验身份认证是否成功 */
            String sysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
            userService.setUserSessionValue(UserSessionConstant.IDENTITY_VERIFY_SEQ_NUM, sysSeqNum);
            //身份验证通过后，将系统流水号作为认证token返回
            modifyUserPhoneResponse.setAuthToken(sysSeqNum);
            bizResponse.setResult(modifyUserPhoneResponse);
            bizResponse.setRspSysId(AppParamConstant.IGAS);
            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            return bizResponse;
        }
        //交易类别 01-手机号修改
        else if ("01".equals(txnMode)) {
            if (StringUtil.isEmptyOrNull(newPhoneNo)) {
                rglog.error("修改用户手机号时未传入新的手机号");
                throw new BizException(RespCodeEnum.PARAM_ERROR.getRespCode(), RespCodeEnum.PARAM_ERROR.getRespDesc());
            }
            //校验身份验证流水号字段，根据session获取会话对象数据，从session对象获取authToken无缓存数据则验证失败；有缓存数据验证通过。验证通过后，设置value为空
            String authTokenValue = userService.getUserSessionValue(UserSessionConstant.IDENTITY_VERIFY_SEQ_NUM);
            if (null == authTokenValue || !authTokenValue.equals(modifyUserPhoneRequest.getAuthToken())) {
                rglog.info("authToken验证失败,sessionAuthToken:<{}>,reqeustAuthToken:<{}>", authTokenValue, modifyUserPhoneRequest.getAuthToken());
                throw new BizException(RespCodeEnum.IDENTITY_INFORM_DISACCORD.getRespCode(), RespCodeEnum.IDENTITY_INFORM_DISACCORD.getRespDesc());
            }
            //查询非金融交易流水表（T_P_NON_FINANCE_TXN）获取身份验证交易结果状态
            rglog.debug("身份验证流水号：<{}>", modifyUserPhoneRequest.getAuthToken());
            NonFinanceTxnMapper nonFinanceTxnMapper = new NonFinanceTxnMapperImpl();
            NonFinanceTxn nonFinanceTxn = nonFinanceTxnMapper.selectNonFinanceTxnInfoByPrimaryKey(instId, modifyUserPhoneRequest.getAuthToken());
            if (nonFinanceTxn == null) {
                rglog.warn("非金融流水表中无该请求短信验证码交易，instId:<{}>,transSeqNum:<{}>", instId, modifyUserPhoneRequest.getAuthToken());
                throw new BizException(RespCodeEnum.VERIFICATION_CODE_INVALID.getRespCode(), RespCodeEnum.VERIFICATION_CODE_INVALID.getRespDesc());
            }
            //状态为“1”（交易成功）时，校验通过,否则，应答“身份验证失败”
            if (!TransStatusEnum.TRANS_SUCC.getStatus().equals(nonFinanceTxn.getTxnStatus())) {
                rglog.warn("身份验证失败!");
                throw new BizException(RespCodeEnum.IDENTITY_INFORM_DISACCORD.getRespCode(), RespCodeEnum.IDENTITY_INFORM_DISACCORD.getRespDesc());
            }
            //校验新手机号短信验证码
            rglog.debug("开始校验短信验证码是否正确");
            String smsCode = modifyUserPhoneRequest.getSmsCode();
            String smsVerifySeqNum = modifyUserPhoneRequest.getSmsVerifySeqNum();
            SmsService smsService = new SmsServiceImpl();
            smsService.verifySmsCode(instId, cc.rengu.oltp.service.common.enums.SmsTypeEnum.MODIFY_PHONE.getSmsType(), smsCode, smsVerifySeqNum);
            //更新用户登录手机号（MOBILE_NO)
            userInfo.setMobileNo(newPhoneNo);
            boolean modifyFlag = userService.updateUserInfo(userInfo);
            if (!modifyFlag) {
                rglog.error("更新收银台用户信息表用户手机号码失败，instId:<{}>,mobileNo<{}>", instId, newPhoneNo);
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            } else {
                rglog.debug("更新收银台用户信息表用户手机号码成功，instId:<{}>,mobileNo<{}>", instId, newPhoneNo);
            }
            //修改成功后更新修改身份验证的存储信息为空
            userService.removeUserSessionValue(UserSessionConstant.IDENTITY_VERIFY_SEQ_NUM);
            //响应
            modifyUserPhoneResponse.setPhoneNo(newPhoneNo);
            bizResponse.setResult(modifyUserPhoneResponse);
            bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            return bizResponse;
        } else {
            rglog.warn("传入参数错误，无法识别的交易类型.txnMode:<{}>", txnMode);
            throw new BizException(RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespCode(), RespCodeEnum.NOT_SURP_TRANS_TYPE_ERROR.getRespDesc());
        }
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        ModifyUserPhoneResponse modifyUserPhoneResponse = (ModifyUserPhoneResponse) bizResponse.getResult();
        ConvertUtil.convertInput(modifyUserPhoneResponse);
    }
}
